﻿using System;
using SmartHRMS.Model.Account;
using SmartHRMS.Infrastructure;
using System.Collections.Generic;
using SmartHRMS.Infrastructure.Caching;

namespace SmartHRMS.Services
{
    public class UserService : IUserService
    {
        private IUserRepository _UserRepository;
        private IUnitOfWork _UnitOfWork;
        private ICacheStorage _CacheStorage;
        string storageCacheKey = "users";

        public UserService(IUserRepository userRepository, IUnitOfWork UnitOfWork, ICacheStorage CacheStorage)
        {
            this._UserRepository = userRepository;
            this._CacheStorage = CacheStorage;
            this._UserRepository.Inject(UnitOfWork);
            this._UnitOfWork = UnitOfWork;
        }

        #region IUserService Members

        public IList<User> FindAll()
        {
            IList<User> users;
            users = _CacheStorage.Retrieve<List<User>>(storageCacheKey);
            if (users == null)
            {
                users = _UserRepository.FindAll();
                _CacheStorage.Store(storageCacheKey, users);
            }
            return users;
        }

        public User FindBy(Guid userId)
        {
            _CacheStorage.Remove(storageCacheKey);
            return _UserRepository.FindBy(userId);
        }

        public IList<User> FindUsersByEmployeeCode(string employeeCode)
        {
           return _UserRepository.FindUsersByEmployeeCode(employeeCode);
        }

        public IList<User> FindUsersByName(string userName)
        {
           return _UserRepository.FindUsersByName(userName);
        }

        public void Remove(User user)
        {
            if (user != null)
            {
                _UserRepository.Remove(user);
                _UnitOfWork.Commit();
                _CacheStorage.Remove(storageCacheKey);
            }
            else
            {
                string brokenRules = BuildErrorListFrom(user);

                throw (new InvalidOperationException(string.Format("The user information is not in a valid state to be deleted. {0}", brokenRules)));
            }
        }

        public void Save(User user)
        {
            if (user.GetBrokenRules().Count > 0)
            {
                string brokenRules = BuildErrorListFrom(user);

                throw (new InvalidOperationException(string.Format("The user information is not in a valid state to be persisted. {0}", brokenRules)));
            }
            else
            {
                _UserRepository.Save(user);
                _UnitOfWork.Commit();
                _CacheStorage.Remove(storageCacheKey);
            }
        }

        public bool AddToRole(Guid roleId)
        {
            return _UserRepository.AddToRole(roleId);
        }

        public bool RemoveRole(Guid roleId)
        {
            return _UserRepository.RemoveRole(roleId);
        }

        public bool IsUserNameExist(string userName)
        {
            return _UserRepository.IsUserNameExist(userName);
        }

        #endregion

        private string BuildErrorListFrom(User user)
        {
            System.Text.StringBuilder brokenRulesList = new System.Text.StringBuilder();

            foreach (BrokenRule brokenRule in user.GetBrokenRules())
            {
                brokenRulesList.Append(brokenRule.Rule);
                brokenRulesList.Append(Environment.NewLine);
            }

            return brokenRulesList.ToString();
        }
    }
}
